<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class LearnController extends Controller
{


    //魔术方法：construct
   /* private  $id;
    private $name;
    private function __construct($id = null, $name=null)
    {
        $this->id = $id;
        $this->name = $name;

    }


    public static function fromBasicData(int $id, string  $name)
    {
        $new = new  static($id, $name);
        return $new;
    }

    public static function formJson(string $json)
    {
        $data = json_decode($json,true);
        return new static($data['id'], $data['name']);
    }

    public function __destruct()
    {
        echo 'Destruct '.$this->name.'--and--'.$this->id.PHP_EOL;
    }
*/



    public  function redis(){
//        $vendorDir = dirname(dirname(__FILE__));
//        $baseDir = dirname($vendorDir);
//        dd($baseDir,$vendorDir,__FILE__);
        $redis = app('redis.connection');

        $redis->set('incr','-346');
        $redis->incr('incr');//key值+1，作用于64位的有符号整形数据，若存贮的不能表示位整数，则异常提示
        $redis->incrby('incr',5);//同上，执行增加多少值
        dd($redis->get('incr'));

        $redis->hset('hset', 'field1','Hello');
        dd($redis->hget('hset'));


        $redis->append('append','ceshi append');//给某个键的value，追加字符串，不存在则同set创建一个空字符串，再累加
//        dd($redis->getrange('append',1,9));//返回key对应的value中的子串，从start开始，到end结束
        dd($redis->getbit('append',8));//0110 0011 0110 0101 0111 0011,返回key对应的value在指定位置offset的bit值，内存存贮都是二进制，所以转为二进制看



        $redis->expire('append',20);//设置过期时间，单位为秒，过期自动删除key
        var_dump($redis->ttl('append'));//返回key剩余的过期时间，单位为秒，-2：key不存在或已过期；-1：key存在且未设置过期时间
        var_dump($redis->get('append'));//返回value，ni1：key不存在；value不是string，就异常
        $redis->set('append','ceshi append dfgfdg');
        var_dump($redis->ttl('append'));
        var_dump($redis->get('append'));
        die;
        dd($redis->exists('append'));//存在返回1，不存在返回0
//        $redis->setnx('yret', date("Y-m-d H:i:s"));
        dd(111);
    }
    //

    public function union(){
        $str = 'fang-zhi-gang';
        dd(ucwords(implode(' ',explode('-',$str))));
        dd(str_replace(' ','',ucwords(str_replace('-',' ', $str))));

        //约瑟夫环问题，猴子选大王，n个猴子，数到m踢出，然后继续，一直数到只剩下一个
        $n = 10;
        $arr = range(1,$n);//10个猴子
        $m = 6;
        $i = 1;
        while (count($arr) > 1){
        }
        return $arr[$i-1];

        //反着输出指定字符串
        $s = '1234567890';
        $o = '';
        $i = 0;
        while(isset($s[$i]) && $s[$i] != null) {
            $o = $s[$i++].$o;
        }
        echo $o;die;




        //将abbcddd 转为 1a2b1c3d
        $str = 'abbc  dddeef';
        $res = '';
        $arr = str_split($str);
        $key = 0;//记录下标，方便计算前面的数字
        for ($i=0 ; $i< count($arr); $i++){
           $this_val = $arr[$i]; //记住字母
            if($arr[$i] == $arr[$i+1]){
                continue ;//前后两个一样的，直接跳过；等到下一轮直接count+1
            }else{
                $res .= ($i - $key + 1).$this_val;//不相等时，计算出前面的数字
                $key = $i + 1;
            }
        }
    }

    public function operator(){



        $array1 = [
            'w'=>'1234',
            's'=>'sdfg',
        ];
        $array2 = [
            'w'=>1234,
            's'=>'vcn',
            'g'=>'vcn',
        ];
        $union = $array1 + $array2;//键相同保留前者，不同则将后者的多余的键与值加给前者
        var_dump($union);
        var_dump($array1 == $array2);// false
        var_dump($array1 === $array2);//false
        var_dump($array1 != $array2);//true
        var_dump($array1 !== $array2);//true
    }


    public function algorithm()
    {
        $arr = [9,8,12,7,44,1];

        /*选择排序（是一种简单只管得排序算法。工作原理是：每一次从待排序得数据元素中选出最小或者最大得一个，存放在元素得最起始位置，知道全部待排序数据原色全部排完。
         * 选择排序并不是最稳定得方法，比如【5，5，3】，第一轮排序就会将第一个5与3交换，导致第一个5挪到了第二个5后面）
         * 简单理解就是：首先默认待排序得第一个元素为最小值A，然后从剩下得序列里，选取最小得值B，判断B<A，就替换两者元素位置，然后继续比较第二个位置，从剩余的队列里面
         * 找到最小的值，放在第二位，一次类推
         * */
/*        for($i=0;$i<$len-1;$i++){
            $min = $i ; //将第一个默认为最小值，接下来从剩下的数据中找出最小值
            for ($j=$i+1; $j<$len;$j++){
                if($arr[$min] > $arr[$j]){
                    //交换两个数据
                    $tem = $arr[$min];
                    $arr[$min] = $arr[$j];
                    $arr[$j] = $tem;
                }
            }
        }*/
        return $this->selectSort($arr);


        /*冒泡排序：比较两个相邻的元素。如果第一个大于第二个，就交换这两个数。对每一对相邻的元素做同样的曹祖直至最后一对。最后一个元素就是最大的值，所以叫冒泡。针对所有的
        元素重复以上元素，除了最后一个，所以持续的比较次数也是越来越少，知道冒泡结束
         *简单理解就是：每一轮比较都会将最大的值冒出来，就像第一轮冒出最大的放在最后，第二轮冒出第二大的放在倒数第二位，同样第二轮比较的时候最后一位已是最大数
         * 无需再参与比较，一次类推，直到总共比较N轮
         * */
        return $this->bubbleSort($arr);


        /*快速排序：通过一趟排序将要排序的数据分割成独立的两部分，其中一部分的数据都比另外一部分的所有数据都小，然后再按照同样的方法对这两部分的数据再次进行快速排序，
        所以整个过程可以递归实现
         * */
        return $this->quickSort($arr);

        /*二分查找：从指定数组中的中间开始查找，然后递归处理
         *
         * */
        return $arr;


    }

    /*
     * 选择排序
     * */
    /*选择排序（是一种简单只管得排序算法。工作原理是：每一次从待排序得数据元素中选出最小或者最大得一个，存放在元素得最起始位置，知道全部待排序数据原色全部排完。
         * 选择排序并不是最稳定得方法，比如【5，5，3】，第一轮排序就会将第一个5与3交换，导致第一个5挪到了第二个5后面）
         * 简单理解就是：首先默认待排序得第一个元素为最小值A，然后从剩下得序列里，选取最小得值B，判断B<A，就替换两者元素位置，然后继续比较第二个位置，从剩余的队列里面
         * 找到最小的值，放在第二位，一次类推
         * */
    protected function selectSort(&$arr){

        for($i=0,$len=count($arr); $i<$len-1;$i++){
            $min = $arr[$i];//默认第一位为最小值,跟剩下的数据各个比较
            for ($j=$i+1; $j<$len;$j++){
                if($min >$arr[$j]){
                    $min = $arr[$j];//把当前元素设置为最小值
                    $min_index= $j;//把最小值对应的位置设置为这个元素的位置
                }
            }
            //内循环结束，吧外循环原来定义的最小值与查找的最小值交换位置
            list($arr[$i], $arr[$min_index]) = array($min, $arr[$i]);
        }

        return $arr;
    }

    /*
     * 冒泡排序,最优的过程
     * */
    protected function bubbleSort(&$arr)
    {
        /*for($i = 0; $i<$len-1; $i++){//此时的$i就是计数比较的轮数，以及此轮需要比较的次数
            for ($j=0; $j <$len-1-$i; $j++){//每轮需要比较的次数
                if($arr[$j] >$arr[$j+1]){
                    $tem = $arr[$j];
                    $arr[$j] = $arr[$j+1];
                    $arr[$j+1] = $tem;
                }
            }
        }*/

        //升级写法：给外循环设置结束点
       /* for($i=0,$len=count($arr); $i<$len; $i++){
            $stop_flag = false; //用来表示什么时候外循环可以停止：当内循环结束，发现没有一个元素的位置被交换
            for($j=0;$j<$len-1-$i;$j++){
                if($arr[$j+1] < $arr[$j]){
                    list($arr[$j], $arr[$j+1]) = array($arr[$j+1], $arr[$j]);
                    $stop_flag = true;
                }
            }

            if(!$stop_flag) break;
        }*/

        //终极写法：再给内循环添加一个介限：当内循环发现此轮比较没有需要交换的，那么下轮内循环的时候，就可以直接少比较，
        //        例如数据9，8，12，1，7，44；当第一轮的时候，i=0，j=0开始，此时下一轮内循环是最大的比较次数为：5，一轮内循环下来，当j=3的时候，发现后面没有需要交换位置的，
        //            那么此轮内循环就可以结束了，下一轮内循环比较次数只需要小于上一轮的3就可以
        for($i = 0,$len = count($arr);$i<$len;$i++){
            $stop_flag = false;//用来表示什么时候外循环可以停止：当内循环结束，发现没有一个元素的位置被交换
            $maopao_count = count($arr)-1;
            for ($j=0;$j<$maopao_count;$j++){
                if($arr[$j+1]<$arr[$j]){
                    list($arr[$j], $arr[$j+1]) = array($arr[$j+1], $arr[$j]);
                    $stop_flag = true;
                    $new_maopao_count = $j ;
                }
            }
            //设置下一次外循环对应的内循环，需要比较的论数
            $maopao_count = $new_maopao_count;
            //内循环所有轮比较下来，没有交换的数据，排序结束
            if(!$stop_flag) break;
        }

        return $arr;

    }

    /*快速排序：通过一趟排序将要排序的数据分割成独立的两部分，其中一部分的数据都比另外一部分的所有数据都小，然后再按照同样的方法对这两部分的数据再次进行快速排序，
        所以整个过程可以递归实现
     * */
    protected function quickSort($arr){
        $len = count($arr);

        if($len <=1){
            return $arr;
        }

        $base = $min = $max =[];
        $base_item = $arr[0]; //以数组的第一个元素，作为划分大小数组的标尺

        for ($i = 0; $i<$len-1; $i++){
            if($arr[$i] > $base_item){
                $max[] = $arr[$i];
            }elseif($arr[$i] < $base_item){
                $min[] = $arr[$i];
            }else{
                $base[] = $arr[$i];
            }
        }

        $min = $this->quickSort($min);
        $max = $this->quickSort($max);
        return array_merge($min, $base ,$max);
    }


}
